﻿//======================================================
//==     (c)2013  OpenLayers.cn inc by 飞龙在天 v1.0  ==
//==          Forum:bbs.OpenLayers.cn                 ==
//==         Website:www.OpenLayers.cn                ==
//== 开源旗舰版见 淘宝: http://giscenter.taobao.com   ==
//======================================================
namespace Common
{
    using System;
    using System.Runtime.InteropServices;

    public class GlobalMercator
    {
        private double Axis = 6378137.0;
        public double initialResolution;
        public double originShift;
        public int tileSize;

        public GlobalMercator(int tileSize = 256)
        {
            this.tileSize = tileSize;
            this.initialResolution = (6.2831853071795862 * this.Axis) / ((double) this.tileSize);
            this.originShift = (6.2831853071795862 * this.Axis) / 2.0;
        }

        public double getMapScale(int zoom)
        {
            return (((this.tileSize * Math.Pow(2.0, (double) zoom)) * 0.0254) / ((this.initialResolution * 96.0) * 256.0));
        }

        public int getMapZoom(double scale)
        {
            int num2 = (int) Math.Round((double) ((((scale * this.initialResolution) * 96.0) * 256.0) / (this.tileSize * 0.0254)));
            return (int) Math.Round(Math.Log((double) num2, 2.0));
        }

        public TMS GoogleTile(double tx, double ty, int zoom)
        {
            return new TMS(tx, (Math.Pow(2.0, (double) zoom) - 1.0) - ty);
        }

        public XY LatLonToMeters(double lat, double lon)
        {
            XY xy2 = new XY();
            xy2.X = (lon * this.originShift) / 180.0;
            xy2.Y = Math.Log(Math.Tan(((90.0 + lat) * 3.1415926535897931) / 360.0)) / 0.017453292519943295;
            xy2.Y = (xy2.Y * this.originShift) / 180.0;
            return xy2;
        }

        public XY LatLonToTile(double lon, double lat, int zoom)
        {
            XY xy2 = this.LatLonToMeters(lon, lat);
            XY xy3 = this.MetersToPixels(xy2.X, xy2.Y, zoom);
            return this.PixelsToTile(xy3.X, xy3.Y);
        }

        public LatLon MetersToLatLon(double x, double y)
        {
            LatLon lon = new LatLon();
            lon.lon = (x / this.originShift) * 180.0;
            lon.lat = (y / this.originShift) * 180.0;
            lon.lat = 57.295779513082323 * ((2.0 * Math.Atan(Math.Exp((lon.lat * 3.1415926535897931) / 180.0))) - 1.5707963267948966);
            return lon;
        }

        public XY MetersToPixels(double x, double y, int zoom)
        {
            double num = this.Resolution(zoom);
            XY xy2 = new XY();
            xy2.X = (x + this.originShift) / num;
            xy2.Y = (y + this.originShift) / num;
            return xy2;
        }

        public XY MetersToTile(double x, double y, int zoom)
        {
            XY xy2 = this.MetersToPixels(x, y, zoom);
            return this.PixelsToTile(xy2.X, xy2.Y);
        }

        public XY PixelsToMeters(double px, double py, int zoom)
        {
            double num = this.Resolution(zoom);
            XY xy = new XY();
            xy.X = (px * num) - this.originShift;
            xy.Y = (py * num) - this.originShift;
            return xy;
        }

        public XY PixelsToTile(double px, double py)
        {
            XY xy = new XY();
            xy.X = Math.Floor((double) (px / ((double) this.tileSize)));
            xy.Y = Math.Floor((double) (py / ((double) this.tileSize)));
            return xy;
        }

        public double Resolution(int zoom)
        {
            return (this.initialResolution / Math.Pow(2.0, (double) zoom));
        }

        public Bounds TileBounds(double tx, double ty, int zoom)
        {
            XY xy2 = this.PixelsToMeters(tx * this.tileSize, ty * this.tileSize, zoom);
            XY xy = this.PixelsToMeters((tx + 1.0) * this.tileSize, (ty + 1.0) * this.tileSize, zoom);
            return new Bounds(xy2.X, xy2.Y, xy.X, xy.Y);
        }

        public Bounds TileLatLonBounds(double tx, double ty, int zoom)
        {
            Bounds bounds = this.TileBounds(tx, ty, zoom);
            LatLon lon2 = this.MetersToLatLon(bounds.MinX, bounds.MinY);
            LatLon lon = this.MetersToLatLon(bounds.MaxX, bounds.MaxY);
            return new Bounds(lon2.lon, lon2.lat, lon.lon, lon.lat);
        }

        public int ZoomForPixelSize(double pixelSize)
        {
            int num3;
            int zoom = 0;
            zoom = 1;
            do
            {
                if (pixelSize > this.Resolution(zoom))
                {
                    if (zoom != 0)
                    {
                        zoom--;
                    }
                    else
                    {
                        zoom = 0;
                    }
                }
                zoom++;
                num3 = 30;
            }
            while (zoom <= num3);
            return zoom;
        }
    }
}

